// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -

float4x4 obj2projection;
float4x4 obj2world;
float4x4 world2obj;

float3 eyePosition;

// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -

float4 materialAmbient = float4 (0.1, 0.1, 0.1, 1.0);
float4 materialDiffuse = float4 (0.7, 0.7, 0.7, 1.0);
float4 materialSpecular = float4 (0.9, 0.9, 0.9, 1.0);
float shininess = 6;

float4 lightAmbient = float4 (0.2, 0.2, 0.2, 1.0);
float4 lightDiffuse = float4 (0.9, 0.9, 0.9, 1.0);
float4 lightSpecular = float4 (0.9, 0.9, 0.9, 1.0);
float3 lightPosition;

float attA = 1.0;
float attB = 0.00001;
float attC = 0.000001;

float considerAlpha = 0.0;

// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -

texture diffuseTexture;

sampler diffuseTextureSampler = sampler_state
{
	texture = <diffuseTexture>;
	AddressU = WRAP;
	AddressV = WRAP;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = POINT;
};

texture specularTexture;

sampler specularTextureSampler = sampler_state
{
	texture = <specularTexture>;
	AddressU = WRAP;
	AddressV = WRAP;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = POINT;
};

texture normalTexture;

sampler normalTextureSampler = sampler_state
{
	texture = <normalTexture>;
	AddressU = WRAP;
	AddressV = WRAP;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = POINT;
};

// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -

struct VShaderInput
{
float4 position : POSITION;
float3 normal   : NORMAL;
float3 binormal : BINORMAL;
float3 tangent  : TANGENT;
float2 tex0     : TEXCOORD0;
};

struct PShaderInput
{
float4 hpos : POSITION;
float4 col0 : COLOR0;
float4 col1 : COLOR1;
float2 tex0 : TEXCOORD0;
float3 L    : TEXCOORD1;
float3 V    : TEXCOORD2;
float3 N    : TEXCOORD3;
float3 TBN0 : TEXCOORD4;
float3 TBN1 : TEXCOORD5;
float3 TBN2 : TEXCOORD6;
};

// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -

PShaderInput vs_phongblinnpixelnormal( VShaderInput input )
{
	PShaderInput result = (PShaderInput)0;
	result.hpos = mul( input.position, obj2projection );
	result.tex0 = input.tex0;
	
	float3 P = mul( input.position, obj2world );
	
	result.L = lightPosition - P;
	result.V = eyePosition - P;

	float3x3 tex2obj = float3x3(input.tangent, input.binormal, input.normal);
	float3x3 tex2world = mul(tex2obj, (float3x3)obj2world);

	result.TBN0 = tex2world[0];
    result.TBN1 = tex2world[1];
    result.TBN2 = tex2world[2];

	return result;
}

float4 ps_phongblinnpixelnormal( PShaderInput input ) : COLOR0
{
	float3 L = normalize( input.L );
	float3 V = normalize( input.V );
	float3 H = normalize( L + V );

	float3x3 tex2world = float3x3(normalize(input.TBN0), normalize(input.TBN1), normalize(input.TBN2));
	float3 N = tex2D(normalTextureSampler, input.tex0) * 2 - 1;
	N = mul(N, tex2world);
	
	float Llength = length(input.L);
	float attenuation = attA + Llength*(attB + Llength*attC); 

	float4 diffusePower = (lightDiffuse * materialDiffuse * saturate( dot( L, N ) ) + lightAmbient * materialAmbient) / attenuation;
	float4 specularPower = lightSpecular * materialSpecular * pow( saturate( dot (H, N) ), shininess ) / attenuation;

	float4 diffuseTexel = tex2D ( diffuseTextureSampler, input.tex0 );
	float4 output = diffuseTexel * diffusePower + specularPower * tex2D ( specularTextureSampler, input.tex0 );
	output.a = diffuseTexel.a * considerAlpha + 1 * (1.0-considerAlpha);
	return output;
}

float4 ps_phongblinnpixelparallax( PShaderInput input ) : COLOR0
{
	float3 L = normalize( input.L );
	float3 V = normalize( input.V );
	float3 H = normalize( L + V );

	float3x3 tex2world = float3x3(normalize(input.TBN0), normalize(input.TBN1), normalize(input.TBN2));

	float3 Vtex = mul(V, tex2world);
	float2 texShift = -Vtex * 0.01 * (tex2D(normalTextureSampler, input.tex0).a * 2 - 1);
	float3 N = tex2D(normalTextureSampler, input.tex0 + texShift) * 2 - 1;

	N = mul(N, tex2world);
	
	float Llength = length(input.L);
	float attenuation = attA + Llength*(attB + Llength*attC); 

	float4 diffusePower = (lightDiffuse * materialDiffuse * saturate( dot( L, N ) ) + lightAmbient * materialAmbient) / attenuation;
	float4 specularPower = lightSpecular * materialSpecular * pow( saturate( dot (H, N) ), shininess ) / attenuation;

	float4 diffuseTexel = tex2D ( diffuseTextureSampler, input.tex0 );
	float4 output = diffuseTexel * diffusePower + specularPower * tex2D ( specularTextureSampler, input.tex0 );
	output.a = diffuseTexel.a * considerAlpha + 1 * (1.0-considerAlpha);
	return output;
}



technique PhongBlinnPixelNormal
{
	pass P0
	{
		AlphaBlendEnable = TRUE;
        DestBlend = INVSRCALPHA;
        SrcBlend = SRCALPHA;
		vertexShader = compile vs_2_0 vs_phongblinnpixelnormal();
		pixelShader = compile ps_2_0 ps_phongblinnpixelnormal();
	}
}

technique PhongBlinnPixelParallax
{
	pass P0
	{
		AlphaBlendEnable = TRUE;
        DestBlend = INVSRCALPHA;
        SrcBlend = SRCALPHA;
		vertexShader = compile vs_2_0 vs_phongblinnpixelnormal();
		pixelShader = compile ps_2_0 ps_phongblinnpixelparallax();
	}
}

// -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- -
